package com.beiding.my.common;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

//引用注册表
@Component
public class QuoteExpressionRegistry {

    @Autowired
    private TypeTableMapperHelper typeTableMapperHelper;

    //生成一条引用条件
    public QuoteExpression quoteCondition(Class<? extends Bo> holder, Class<? extends Bo> target, String selfName) {

        QuoteExpression q = (QuoteExpression) Cache.get("QuoteExpressionRegistry.quoteCondition", holder, target);
        if (q == null) {
            synchronized (this) {
                if ((q = (QuoteExpression) Cache.get("QuoteExpressionRegistry.quoteCondition", holder, target)) == null) {
                    q = new QuoteExpression();
                    Class tbe = BoVoBe.getBeTypeFromBoType(target);
                    q.getBeTypes().add(tbe);
                    TypeTableMapper sTypeTableMapper = typeTableMapperHelper.getTypeTableMapper(tbe);
                    TypeTableMapper quote = typeTableMapperHelper.getTypeTableMapper(tbe.getPackage().getName() + "._Quote_" + tbe.getSimpleName());
                    q.getBeTypes().add(quote.getType());
                    Map<String, String> quoteF2c = quote.getFieldToTableColMap();
                    Set<String> conditions = new HashSet<>();
                    String sTable = sTypeTableMapper.getTableName();
                    conditions.add(quote.getTableName() + "." + quoteF2c.get("self") + " = " + sTable + "." + sTypeTableMapper.getFieldToTableColMap().get("id"));
                    q.quoteConditions = conditions;

                    q.expression = quote.getTableName() + "." + quoteF2c.get("_" + BoVoBe.getBeTypeFromBoType(holder).getSimpleName() + "_" + selfName) + " = :holderId";

                    Cache.put(q, "QuoteExpressionRegistry.quoteCondition", holder, target);
                }
            }
        }
        return q;
    }

    public QuoteExpression getQuoteExpression(Class<? extends Bo> clazz, String expression) {

        QuoteExpression q = (QuoteExpression) Cache.get("QuoteExpressionRegistry.getQuoteExpression", clazz, expression);

        if (q == null) {
            synchronized (this) {
                if ((q = (QuoteExpression) Cache.get("QuoteExpressionRegistry.getQuoteExpression", clazz, expression)) == null) {
                    String[] split = expression.split("\\.");

                    //如果长度只有一个
                    if (split.length == 1) {
                        try {
                            q = new QuoteExpression();
                            q.getBeTypes().add(BoVoBe.getBeTypeFromBoType(clazz));
                            TypeTableMapper fTypeTableMapper = typeTableMapperHelper.getTypeTableMapperFromBo(clazz);
                            q.expression = fTypeTableMapper.getTableName() + "." + fTypeTableMapper.getFieldToTableColMap().get(expression);
                            q.quoteConditions = new HashSet<>();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }

                    } else {
                        try {
                            q = new QuoteExpression();

                            //所有条件
                            Set<String> conditions = new HashSet<>();

                            //父层的bo类型
                            Class<? extends Bo> fBoType = clazz;

                            //本层的be类型
                            Class<?> beType = BoVoBe.getBeTypeFromBoType(fBoType);

                            //将涉及到的be类型添加
                            q.getBeTypes().add(beType);

                            //获取类型表映射
                            TypeTableMapper fTypeTableMapper = typeTableMapperHelper.getTypeTableMapper(beType);

                            //父层表名
                            String fTable = fTypeTableMapper.getTableName();

                            for (int i = 0; i < split.length - 1; i++) {

                                //获取本层字段名
                                String filed = split[i];

                                //生成getter方法
                                String methodName;
                                if (filed.length() == 1) {
                                    methodName = "get" + filed.toUpperCase();
                                } else {
                                    methodName = "get" + filed.substring(0, 1).toUpperCase() + filed.substring(1);
                                }

                                //从getter方法的返回值类型确定本层类型名称
                                Class<? extends Bo> sBoType = (Class<? extends Bo>) fBoType.getMethod(methodName).getReturnType();
                                //本层be类型
                                Class sBeType = BoVoBe.getBeTypeFromBoType(sBoType);

                                //将涉及到的be类型添加
                                q.getBeTypes().add(sBeType);

                                //构建引用关系子句
                                TypeTableMapper sTypeTableMapper = typeTableMapperHelper.getTypeTableMapper(sBeType);
                                TypeTableMapper quote = typeTableMapperHelper.getTypeTableMapper(sBeType.getPackage().getName() + "._Quote_" + sBeType.getSimpleName());
                                q.getBeTypes().add(quote.getType());
                                Map<String, String> quoteF2c = quote.getFieldToTableColMap();
                                String sTable = sTypeTableMapper.getTableName();
                                conditions.add(quote.getTableName() + "." + quoteF2c.get("self") + " = " + sTable + "." + sTypeTableMapper.getFieldToTableColMap().get("id"));
                                conditions.add(quote.getTableName() + "." + quoteF2c.get("_" + beType.getSimpleName() + "_" + filed) + " = " + fTable + "." + fTypeTableMapper.getFieldToTableColMap().get("id"));

                                //更新父层引用
                                fBoType = sBoType;
                                fTable = sTable;
                                beType = sBeType;
                                fTypeTableMapper = sTypeTableMapper;
                            }

                            //转换后的sql表达式
                            q.expression = fTypeTableMapper.getTableName() + "." + fTypeTableMapper.getFieldToTableColMap().get(split[split.length - 1]);
                            //引用关系sql子句
                            q.quoteConditions = conditions;
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }

                        //放入缓存
                        Cache.put(q, "QuoteExpressionRegistry.getQuoteExpression", clazz, expression);
                    }

                }
            }
        }
        return q;
    }

    public static class QuoteExpression {
        private Set<String> quoteConditions;
        private String expression;
        private Set<Class> beTypes = new HashSet<>();
        public Set<Class> getBeTypes() {
            return beTypes;
        }
        public Set<String> getQuoteConditions() {
            return quoteConditions;
        }
        public String getExpression() {
            return expression;
        }
    }


}
